package controllers

import command.CommandExec
import dao._
import models.Tables._
import org.joda.time.DateTime
import play.api.libs.json.Json
import play.api.mvc.{AbstractController, ControllerComponents}
import tool.{FormTool, Tool}

import java.io.File
import java.nio.file.Files
import javax.inject.Inject
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import implicits.Implicits._
import tool.Pojo.CommandData
import utils.Utils

/**
 * Created by yz on 16/9/2021
 */
class DataController @Inject()(cc: ControllerComponents)(
  implicit val userDao: UserDao,
  implicit val sampleDao: SampleDao,
) extends AbstractController(cc) {


  def loadDataBefore() = Action { implicit request =>
    Ok(views.html.user.data.loadData())
  }

  def sampleNameCheck = Action.async { implicit request =>
    val data = FormTool.sampleNameForm.bindFromRequest.get
    val idOp = FormTool.idOpForm.bindFromRequest().get.id
    val userId = Tool.getUserId
    idOp.map { id =>
      sampleDao.selectById(id).flatMap { row =>
        sampleDao.selectBySampleName(userId, data.sampleName).map {
          case Some(y) => {
            val valid = (row.sampleName == data.sampleName)
            Ok(Json.obj("valid" -> valid))
          }
          case None => Ok(Json.obj("valid" -> true))
        }
      }
    }.getOrElse {
      sampleDao.selectBySampleName(userId, data.sampleName).map {
        case Some(y) =>
          Ok(Json.obj("valid" -> false))
        case None => Ok(Json.obj("valid" -> true))
      }
    }
  }

  def loadData = Action.async(parse.multipartFormData) { implicit request =>
    val data = FormTool.sampleNameForm.bindFromRequest.get
    val describeData = FormTool.describeForm.bindFromRequest.get
    val tmpDataFile = request.body.file("file").get
    val tmpFile = Files.createTempFile("data", ".fa").toFile
    tmpDataFile.ref.moveTo(tmpFile, true)
    val b = Tool.isFastaFile(tmpFile)
    if (!b) {
      tmpFile.delete()
      Future.successful(Ok(Json.obj("valid" -> false, "message" -> "请选择一个合法的fasta文件!")))
    } else {
      val attr = Tool.getFastaAttr(tmpFile)
      val userId = Tool.getUserId
      val row = SampleRow(0, userId, data.sampleName, describeData.describe, attr.maxLength, attr.minLength, attr.meanLength, attr.size,
        attr.kind, new DateTime())
      sampleDao.insert(row).flatMap(_ => sampleDao.selectBySampleName(userId, data.sampleName).map(_.get)).map { sample =>
        val userIdDir = new File(Tool.userDir, userId.toString).createDirectoryWhenNoExist
        val dataFile = new File(userIdDir, "data").createDirectoryWhenNoExist
        val missionFile = new File(userIdDir, "mission").createDirectoryWhenNoExist
        val file = Tool.getSampleFileById(sample.id)
        tmpFile.copyTo(file)
        val command =
          s"""
             | ${Tool.makeBlastDbFile.unixPath} -in ${file.unixPath} -dbtype nucl
             |""".stripMargin
        val execCommand = CommandExec().exec { b =>
          CommandData(Tool.userDir, List(command))
        }
        if (execCommand.isSuccess) {
          Ok(Json.obj("valid" -> true))
        } else {
          Ok(Json.obj("valid" -> false, "message" -> execCommand.errorInfo))
        }

      }
    }
  }

  def sampleManage = Action { implicit request =>
    Ok(views.html.user.data.sampleManage())
  }

  def getAllSample = Action.async { implicit request =>
    val userId = Tool.getUserId
    sampleDao.selectAll(userId).map { x =>
      val array = Utils.getArrayByTs(x)
      Ok(Json.toJson(array))
    }
  }

  def deleteSamples = Action.async {
    implicit request =>
      val data = FormTool.idsForm.bindFromRequest().get
      sampleDao.deletes(data.ids).map { x =>
        Future {
          data.ids.foreach { id =>
            val file = Tool.getSampleFileById(id)
            file.deleteQuietly
          }
        }
        Ok(Json.toJson("success"))
      }
  }

  def getSampleById = Action.async { implicit request =>
    val data = FormTool.idForm.bindFromRequest().get
    sampleDao.selectById(data.id).map { x =>
      Ok(x.myAsJson)
    }
  }

  def updateSample = Action.async { implicit request =>
    val data = FormTool.sampleForm.bindFromRequest().get
    sampleDao.selectById(data.id).flatMap { x =>
      val row = x.copy(describe = data.describe, sampleName = data.sampleName)
      sampleDao.update(row)
    }.map { x =>
      Ok("success")
    }

  }


}
